package adapter

import (
	"context"
	"errors"
	"google.golang.org/grpc/metadata"
	"migration-tool/common"
	"migration-tool/target"
	"os"
	"os/exec"
)

const (
	FileNotExist = "文件不存在，无需调用Rpc"
)

func GetAuthContext(appKey string, appSecret string) context.Context {
	token := common.GenerateToken(appKey, appSecret)
	md := metadata.Pairs(common.RpcTokenKeyAppKey, appKey, common.RpcTokenKeyAppTokenKey, token)
	//ctx, cancel := context.WithTimeout(context.Background(), 1000*time.Second)
	//defer cancel()
	return metadata.NewOutgoingContext(context.Background(), md)
}

func codeupDealDeployKeysSetting(args TaskArgs) error {
	recordArgs := RecordArgs{
		Log:      args.Log,
		TaskName: args.TaskName,
		Err:      nil,
		Export:   false,
	}
	var data target.CodeupDeployKeysSettingList
	readDataArgs := DataArgs{
		ExportDataDir:      args.ExportDataDir,
		ExportPlatformName: args.ExportPlatformName,
		FileName:           BinFileNameDeployKeysSetting,
		FilePathTmpl:       ExportDataFileTmpl,
		RepoInfo:           args.RepoInfo,
		Data:               &data,
	}
	_, err := ReadProtoData(readDataArgs)
	if os.IsNotExist(err) {
		recordArgs.Msg = FileNotExist
		recordTask(recordArgs)
		return nil
	} else if err != nil {
		return err
	}

	ctx := GetAuthContext(args.AppKey, args.AppSecret)
	client := target.NewCodeupServiceClient(args.Conn)
	resp, err := client.ImportCodeupDeployKeysSetting(ctx, &data)

	if err != nil {
		return err
	}

	if !resp.Success {
		recordArgs.Msg = resp.Msg
		recordTask(recordArgs)
		return errors.New(ErrorMsgRpcResponseError + resp.Msg)
	}
	return nil
}

func codeupDealWebHookSetting(args TaskArgs) error {
	recordArgs := RecordArgs{
		Log:      args.Log,
		TaskName: args.TaskName,
		Err:      nil,
		Export:   false,
	}
	var data target.CodeupWebHookSettingList
	readDataArgs := DataArgs{
		ExportDataDir:      args.ExportDataDir,
		ExportPlatformName: args.ExportPlatformName,
		FileName:           BinFileNameWebHookSetting,
		FilePathTmpl:       ExportDataFileTmpl,
		RepoInfo:           args.RepoInfo,
		Data:               &data,
	}
	_, err := ReadProtoData(readDataArgs)
	if os.IsNotExist(err) {
		recordArgs.Msg = FileNotExist
		recordTask(recordArgs)
		return nil
	} else if err != nil {
		return err
	}

	ctx := GetAuthContext(args.AppKey, args.AppSecret)
	client := target.NewCodeupServiceClient(args.Conn)
	resp, err := client.ImportCodeupWebHookSetting(ctx, &data)

	if err != nil {
		return err
	}

	if !resp.Success {
		recordArgs.Msg = resp.Msg
		recordTask(recordArgs)
		return errors.New(ErrorMsgRpcResponseError + resp.Msg)
	}
	return nil
}

func codeupDealPushRuleSetting(args TaskArgs) error {
	recordArgs := RecordArgs{
		Log:      args.Log,
		TaskName: args.TaskName,
		Err:      nil,
		Export:   false,
	}
	var data target.CodeupPushRuleSettingList
	readDataArgs := DataArgs{
		ExportDataDir:      args.ExportDataDir,
		ExportPlatformName: args.ExportPlatformName,
		FileName:           BinFileNamePushRuleSetting,
		FilePathTmpl:       ExportDataFileTmpl,
		RepoInfo:           args.RepoInfo,
		Data:               &data,
	}
	_, err := ReadProtoData(readDataArgs)
	if os.IsNotExist(err) {
		recordArgs.Msg = FileNotExist
		recordTask(recordArgs)
		return nil
	} else if err != nil {
		return err
	}

	ctx := GetAuthContext(args.AppKey, args.AppSecret)
	client := target.NewCodeupServiceClient(args.Conn)
	resp, err := client.ImportCodeupPushRuleSetting(ctx, &data)

	if err != nil {
		return err
	}

	if !resp.Success {
		recordArgs.Msg = resp.Msg
		recordTask(recordArgs)
		return errors.New(ErrorMsgRpcResponseError + resp.Msg)
	}
	return nil
}

func codeupDealCodeReviewSetting(args TaskArgs) error {
	recordArgs := RecordArgs{
		Log:      args.Log,
		TaskName: args.TaskName,
		Err:      nil,
		Export:   false,
	}
	var data target.CodeupCodeReviewSetting
	readDataArgs := DataArgs{
		ExportDataDir:      args.ExportDataDir,
		ExportPlatformName: args.ExportPlatformName,
		FileName:           BinFileNameCodeReviewSetting,
		FilePathTmpl:       ExportDataFileTmpl,
		RepoInfo:           args.RepoInfo,
		Data:               &data,
	}
	_, err := ReadProtoData(readDataArgs)
	if os.IsNotExist(err) {
		recordArgs.Msg = FileNotExist
		recordTask(recordArgs)
		return nil
	} else if err != nil {
		return err
	}

	ctx := GetAuthContext(args.AppKey, args.AppSecret)
	client := target.NewCodeupServiceClient(args.Conn)
	resp, err := client.ImportCodeupCodeReviewSetting(ctx, &data)

	if err != nil {
		return err
	}

	if !resp.Success {
		recordArgs.Msg = resp.Msg
		recordTask(recordArgs)
		return errors.New(ErrorMsgRpcResponseError + resp.Msg)
	}
	return nil
}

func codeupDealProtectBranchSetting(args TaskArgs) error {
	recordArgs := RecordArgs{
		Log:      args.Log,
		TaskName: args.TaskName,
		Err:      nil,
		Export:   false,
	}
	var data target.CodeupProtectBranchSettingList
	readDataArgs := DataArgs{
		ExportDataDir:      args.ExportDataDir,
		ExportPlatformName: args.ExportPlatformName,
		FileName:           BinFileNameProtectBranchSetting,
		FilePathTmpl:       ExportDataFileTmpl,
		RepoInfo:           args.RepoInfo,
		Data:               &data,
	}
	_, err := ReadProtoData(readDataArgs)
	if os.IsNotExist(err) {
		recordArgs.Msg = FileNotExist
		recordTask(recordArgs)
		return nil
	} else if err != nil {
		return err
	}

	ctx := GetAuthContext(args.AppKey, args.AppSecret)
	client := target.NewCodeupServiceClient(args.Conn)
	resp, err := client.ImportProtectBranchSetting(ctx, &data)

	if err != nil {
		return err
	}

	if !resp.Success {
		recordArgs.Msg = resp.Msg
		recordTask(recordArgs)
		return errors.New(ErrorMsgRpcResponseError + resp.Msg)
	}
	return nil
}

func codeupDealRepoMetaInfo(args TaskArgs) error {
	recordArgs := RecordArgs{
		Log:      args.Log,
		TaskName: args.TaskName,
		Err:      nil,
		Export:   false,
	}
	var data target.CodeupRepoMetaInfo
	readDataArgs := DataArgs{
		ExportDataDir:      args.ExportDataDir,
		ExportPlatformName: args.ExportPlatformName,
		FileName:           BinFileNameRepoMetaInfo,
		FilePathTmpl:       ExportDataFileTmpl,
		RepoInfo:           args.RepoInfo,
		Data:               &data,
	}
	_, err := ReadProtoData(readDataArgs)
	if os.IsNotExist(err) {
		recordArgs.Msg = FileNotExist
		recordTask(recordArgs)
		return nil
	} else if err != nil {
		return err
	}

	ctx := GetAuthContext(args.AppKey, args.AppSecret)
	client := target.NewCodeupServiceClient(args.Conn)
	resp, err := client.ImportRepoMetaInfo(ctx, &data)

	if err != nil {
		return err
	}

	if !resp.Success {
		recordArgs.Msg = resp.Msg
		recordTask(recordArgs)
		return errors.New(ErrorMsgRpcResponseError + resp.Msg)
	}

	return nil
}

func codeupDealCode(args TaskArgs) error {
	recordArgs := RecordArgs{
		Log:      args.Log,
		TaskName: args.TaskName,
		Err:      nil,
		Export:   false,
	}
	var data target.CodeupRepoMetaInfo
	readDataArgs := DataArgs{
		ExportDataDir:      args.ExportDataDir,
		ExportPlatformName: args.ExportPlatformName,
		FileName:           BinFileNameRepoMetaInfo,
		FilePathTmpl:       ExportDataFileTmpl,
		RepoInfo:           args.RepoInfo,
		Data:               &data,
	}
	_, err := ReadProtoData(readDataArgs)
	if os.IsNotExist(err) {
		recordArgs.Msg = FileNotExist
		recordTask(recordArgs)
		return nil
	} else if err != nil {
		return err
	}

	readDataArgs = DataArgs{
		ExportDataDir:      args.ExportDataDir,
		ExportPlatformName: args.ExportPlatformName,
		FilePathTmpl:       CloneRepoFileTmpl,
		RepoInfo:           args.RepoInfo,
		Data:               nil,
	}

	dir, err := MkdirFromStringTmpl(readDataArgs)
	if err != nil {
		return err
	}

	_, err = os.Stat(dir)
	if os.IsNotExist(err) {
		return errors.New("仓库代码不存在")
	} else if err != nil {
		return err
	}

	ctx := GetAuthContext(args.AppKey, args.AppSecret)
	client := target.NewCodeupServiceClient(args.Conn)
	resp, err := client.GetRepoPushUrl(ctx, &data)

	if err != nil {
		return err
	}

	if !resp.Success {
		recordArgs.Msg = resp.Msg
		recordTask(recordArgs)
		return errors.New(ErrorMsgRpcResponseError + resp.Msg)
	}

	var cmd *exec.Cmd
	cmd = exec.Command("git", "-C", dir, "push", "--mirror", resp.RepoHttpCloneUrl)

	if err = cmd.Run(); err != nil {
		recordArgs.Err = err
		recordTask(recordArgs)
		return err
	}

	recordArgs.Msg = "仓库推送成功"
	recordTask(recordArgs)
	return nil
}

func codeupDealWiki(args TaskArgs) error {
	recordArgs := RecordArgs{
		Log:      args.Log,
		TaskName: args.TaskName,
		Err:      nil,
		Export:   false,
	}
	var data target.CodeupRepoMetaInfo
	readDataArgs := DataArgs{
		ExportDataDir:      args.ExportDataDir,
		ExportPlatformName: args.ExportPlatformName,
		FileName:           BinFileNameRepoMetaInfo,
		FilePathTmpl:       ExportDataFileTmpl,
		RepoInfo:           args.RepoInfo,
		Data:               &data,
	}
	_, err := ReadProtoData(readDataArgs)
	if os.IsNotExist(err) {
		recordArgs.Msg = FileNotExist
		recordTask(recordArgs)
		return nil
	} else if err != nil {
		return err
	}

	readDataArgs = DataArgs{
		ExportDataDir:      args.ExportDataDir,
		ExportPlatformName: args.ExportPlatformName,
		FilePathTmpl:       CloneWikiFileTmpl,
		RepoInfo:           args.RepoInfo,
		Data:               nil,
	}

	dir, err := MkdirFromStringTmpl(readDataArgs)
	if err != nil {
		return err
	}

	_, err = os.Stat(dir)
	if os.IsNotExist(err) {
		return errors.New("仓库wiki不存在")
	} else if err != nil {
		return err
	}

	ctx := GetAuthContext(args.AppKey, args.AppSecret)
	client := target.NewCodeupServiceClient(args.Conn)
	resp, err := client.ImportWiki(ctx, &data)

	if err != nil {
		return err
	}

	if !resp.Success {
		recordArgs.Msg = resp.Msg
		recordTask(recordArgs)
		return errors.New(ErrorMsgRpcResponseError + resp.Msg)
	}

	var cmd *exec.Cmd
	cmd = exec.Command("git", "-C", dir, "push", "--mirror", resp.RepoCloneUrl)

	if err = cmd.Run(); err != nil {
		recordArgs.Err = err
		recordTask(recordArgs)
		return err
	}

	recordArgs.Msg = "仓库推送成功"
	recordTask(recordArgs)
	return nil
}

func codeupDealRepoMember(args TaskArgs) error {
	recordArgs := RecordArgs{
		Log:      args.Log,
		TaskName: args.TaskName,
		Err:      nil,
		Export:   false,
	}
	var data target.CodeupMemberList
	readDataArgs := DataArgs{
		ExportDataDir:      args.ExportDataDir,
		ExportPlatformName: args.ExportPlatformName,
		FileName:           BinFileNameRepoMembers,
		FilePathTmpl:       ExportDataFileTmpl,
		RepoInfo:           args.RepoInfo,
		Data:               &data,
	}
	_, err := ReadProtoData(readDataArgs)
	if os.IsNotExist(err) {
		recordArgs.Msg = FileNotExist
		recordTask(recordArgs)
		return nil
	} else if err != nil {
		return err
	}

	ctx := GetAuthContext(args.AppKey, args.AppSecret)
	client := target.NewCodeupServiceClient(args.Conn)
	resp, err := client.ImportRepoMembers(ctx, &data)

	if err != nil {
		return err
	}

	if !resp.Success {
		recordArgs.Msg = resp.Msg
		recordTask(recordArgs)
		return errors.New(ErrorMsgRpcResponseError + resp.Msg)
	}
	return nil
}

func codeupDealMergeRequest(args TaskArgs) error {
	recordArgs := RecordArgs{
		Log:      args.Log,
		TaskName: args.TaskName,
		Err:      nil,
		Export:   false,
	}
	var data target.CodeupMergeRequestList
	readDataArgs := DataArgs{
		ExportDataDir:      args.ExportDataDir,
		ExportPlatformName: args.ExportPlatformName,
		FileName:           BinFileNameMergeRequests,
		FilePathTmpl:       ExportDataFileTmpl,
		RepoInfo:           args.RepoInfo,
		Data:               &data,
	}
	_, err := ReadProtoData(readDataArgs)
	if os.IsNotExist(err) {
		recordArgs.Msg = FileNotExist
		recordTask(recordArgs)
		return nil
	} else if err != nil {
		return err
	}

	ctx := GetAuthContext(args.AppKey, args.AppSecret)
	client := target.NewCodeupServiceClient(args.Conn)
	resp, err := client.ImportCodeupMergeRequest(ctx, &data)
	if err != nil {
		return err
	}

	if !resp.Success {
		recordArgs.Msg = resp.Msg
		recordTask(recordArgs)
		return errors.New(ErrorMsgRpcResponseError + resp.Msg)
	}
	return nil
}

func globalCodeupDealUser(args TaskArgs) error {
	recordArgs := RecordArgs{
		Log:      args.Log,
		TaskName: args.TaskName,
		Err:      nil,
		Export:   false,
	}
	var data target.CodeupUserList
	readDataArgs := DataArgs{
		ExportDataDir:      args.ExportDataDir,
		ExportPlatformName: args.ExportPlatformName,
		FileName:           BinFileNameAllUsersProto,
		FilePathTmpl:       ExportEnterpriseFileTmpl,
		Data:               &data,
	}
	_, err := ReadProtoData(readDataArgs)
	if os.IsNotExist(err) {
		recordArgs.Msg = FileNotExist
		recordTask(recordArgs)
		return nil
	} else if err != nil {
		return err
	}

	ctx := GetAuthContext(args.AppKey, args.AppSecret)
	client := target.NewCodeupServiceClient(args.Conn)
	resp, err := client.ImportCodeupUsers(ctx, &data)
	if err != nil {
		return err
	}

	if !resp.Success {
		recordArgs.Msg = resp.Msg
		recordTask(recordArgs)
		return errors.New(ErrorMsgRpcResponseError + resp.Msg)
	}

	return nil
}

func globalCodeupDealGroupMember(args TaskArgs) error {
	recordArgs := RecordArgs{
		Log:      args.Log,
		TaskName: args.TaskName,
		Err:      nil,
		Export:   false,
	}
	var data target.CodeupMemberList
	readDataArgs := DataArgs{
		ExportDataDir:      args.ExportDataDir,
		ExportPlatformName: args.ExportPlatformName,
		FileName:           BinFileNameGroupMembers,
		FilePathTmpl:       ExportEnterpriseFileTmpl,
		Data:               &data,
	}
	_, err := ReadProtoData(readDataArgs)
	if os.IsNotExist(err) {
		recordArgs.Msg = FileNotExist
		recordTask(recordArgs)
		return nil
	} else if err != nil {
		return err
	}

	ctx := GetAuthContext(args.AppKey, args.AppSecret)
	client := target.NewCodeupServiceClient(args.Conn)
	resp, err := client.ImportGroupMembers(ctx, &data)
	if err != nil {
		return err
	}

	if !resp.Success {
		recordArgs.Msg = resp.Msg
		recordTask(recordArgs)
		return errors.New(ErrorMsgRpcResponseError + resp.Msg)
	}
	return nil
}
